高速エディタアセンブラ REDA ――――――――――――――――――――――――――――――――――――――― Oh!X 1989年 2月号掲載 S−OS SWORD マシン語  REDA.SOS   03000H−04FFFH S:03000H ZEDA用ソース  REDA−ASM.ASC   (アセンブラ)  REDA−EDITOR.ASC(エディタ ) 起動方法 REDA.SOSをロード J3000 コールドスタート 03000H ホット スタート 03003H *ソースのアセンブルは個別で行います ――――――――――――――――――――――――――――――――――――――― 全機種共通S−OS“SWORD”要 高速エディタアセンブラ  R E D A お待たせしました。 ZEDAに代わるS−OS用のエディタアセンブラを発表します。 今回のマシン語特集で使われていた Z80用アセンブルリストは すべてこのREDAで出力されています。 開発、入門用としてぜひ入力してください。 REDA(Rapid EDitor Assembler)は S−OS“SWORD”上で動作するZ80エディタアセンブラです。 これまでOh!Xの標準アセンブラとして使われてきた ZEDA(EDASM)、およびその改良・高速版ZEDA−3と比べて、 以下のような長所を持っています。 1)アセンブル速度がZEDA−3の2〜数倍。   元祖ZEDAとは比べるのがかわいそうなくらいです。 2)エディタ部分を切り離し、アセンブラのみでも動作可能です。   これにより、テキストやオブジェクトを格納する領域を   いくらか大きく確保することができます。 3)専用エディタとの組み合わせにより、   快適なデバッグ環境を提供します。   アセンブルエラーが起きると、   自動的にエディタに切り換わり、   エラーの発生した行/位置を表示しますから、   即、修正が行えます。 4)専用エディタ使用時は、複数のスペースを   1バイトのタブコードに置き換えるので、   ソースファイルのサイズが小さくてすみます。 5)分割アセンブルが使いやすいかたちに改良されています。   ファイル名を与えるだけで、   自動的にロード/アセンブル(必要ならセーブも)します。 6)いくつかのアセンブルオプションにより、   エラーチェックを厳しくすることができます。   ORGのつけ忘れによる暴走も回避できます。 7)ZEDAが掲載された号はすでに入手が不可能でしたが、   今月号は「ここ」にあります。 ただ、次のような短所もあります。 1)プログラムサイズが若干大きくなってしまいました。   ですが、アセンブラ単体でも動作可能ですので、   すでにE−MATEやWINERをお持ちの方は、   とりあえずアセンブラだけを入力して使うことができます。   この場合、長所の3)、4)が犠牲になりますから、   最終的には専用エディタも入力し、   セットで使うことをお勧めします。 2)ZEDAにあった疑似マクロ命令はサポー卜していません。   また、マルチステートメントも許していません。 3)リロケータブルアセンブラでなければ   マクロアセンブラでもありません。   なんの飾りもない2パスのアブソリュートアセンブラです。   名前は「レダ」と読んでください。 ・―               ―・ |     入力&実行方法     | ・―               ―・ リスト1を各機種のモニタないしは MACINTO−Cなどの マシン語入力ツールから打ち込み、 チェックサム、CRCにより 打ち込み問違いがないことを確認したうえで 3000H〜4FFFHの範囲を実行アドレス3000Hで テープ/ディスクにセーブしてください。 また、アセンブラのみを使おうという方は 3005H番地を00Hに変更したうえで 3000H〜45FFHの範囲をセーブしてください。 S−OS“SWORD”のモニタから、   #J3000 と入力すると、アセンブラモードでコールドスタートします。 また、3003H番地にジャンプすればホットスタートします。 コールドスタートとホットスタートの違いは、囲みのとおりです。 ・――――――――――――――――――――――・ |コールドスタートとホットスタートの違い   | |                      | |コールドスタート(J3000)         | | タイトルを表示したうえで、        | | 特殊ワークの大きさに応じて        | | ハッシュテーブルの大きさを決める。    | | 続いてソーステキスト格納アドレス、    | | オブジェクト生成可能メモリアドレス、   | | ラベルテーブルの大きさ、         | | 並びに使用可能なラベルの最大数、     | | さらにオブジェクトをセーブするときの   | | デバイス名を表示する。          | | さらに、専用エディタが組み込まれていれば、| | テキストエリアの初期化を行う。      | | エディタが組み込まれていなければ     | | テキストエリアの初期化は行わない。    | | 以上の初期設定がすんだら         | | アセンブラのコマンドモードに入る。    | |                      | |ホットスタート(J3003)          | | 一切のメッセージを出さず、        | | テキストエリアの初期化も行わないで、   | | アセンブラのコマンドモードに入る。    | |                      | ・――――――――――――――――――――――・ ===================      エディタ部     〈エディタの使い方〉 ――――――――――――――――――― REDAのエディタは BASICと同様のカーソルエディタです。 最初にアセンブラを起動して、   :E でエディタが起動します。 エディタを起動すると行番号が0001と表示され、 画面の下にプロンプト“>”が表示されて カーソルが点滅を始めます。 このような状態をエディタのコマンドモードと呼びます。 アセンブラをホットスタートするか、 いったんエディタを抜けたあと再びエディタを起動すると、 作成されているテキストが画面に行番号つきで表示され、 コマンドモードに入ります。 表1にコマンドモードで使用できるコマンドを挙げておきます。 表1 コマンドモード ・―――――――――――――――――――――――――――・ | E:エディットモードに入る。            | |   カーソルは画面最上行の入力開始位置に移動    | | V:次の画面を表示                 | | Z:前の画面を表示                 | | G:表示を開始する行番号入力            | | S:検索(順方向のみ)               | | C:置換(順方向のみ)               | | F:ファイルのロード/セーブ            | | N:編集中のテキストを破棄             | | R:破棄したテキストを復活             | | T:テキスト格納アドレスを変更           | | M:メモリの使用状況をレポート           | ・―――――――――――――――――――――――――――・ ・―               ―・ |     コマンドモード     | ・―               ―・ コマンドモードでは、 主ファイルの入出力、文字列の検索/置換、 テキストの連続スクロールを行います。 主なコマンドの使用法を説明しておきましょう。 ●指定した行から表示する “G”コマンドを入力すると、表示を開始する行番号をたずねてきます。 表示を開始したい行番号を入力してください。 行番号は1〜9999までで、 存在しない行番号を指定するとテキストの最後が表示されます。 テキストの最後にはなにもありませんので、 画面にはプロンプトだけが表示されます。 “Z”コマンドで逆スクロールさせると 1ページ分バックし、前の画面を見ることができます。 ●ファイル入出力 “F”を入力すると、 「Load,Save,Get-cut,Cut-save,Dir」と表示されます。 Loadは別のテキストのロードです。 Saveは現在編集中のテキストのセーブ。 Get-cut 、Cut-saveは、 カットバッファヘのテキストの読み込みと、 カットバッファのセーブを行います。 いずれも先頭の1文字を入力してください。 カットバッファについてはエディットモードで説明します。 Get-cut とCut-saveの2つのコマンドは、 別のテキストを現在のテキストに読み込むため、 現在のテキストの一部をセーブするために用意してあります。 使用したファイル名は保存されていますので、 ロード/セーブ方法を指示すると、 現在覚えているファイル名を表示して変更待ちになります。 ファイル名が不明のときはサブコマンドDでディレクトリを表示し、 ファイル名を取り込んでからファイル操作をやり直してください。 ●文字列の置換/検索 文字列の検索、置換を実行すると、 「Begin,Here」と表示されます。 テキストの最初から行うのか、 現在行から行うのかを選択するわけです。 現在行とは、現在、画面のいちばん上の行を指します。 頭文字でいずれかを選択すると、 最新の検索語が表示され、修正を促します。 OKならそのままリターンキーを押してください。 置換の場合はさらに最新の置換語が表示されますので、 こちらもOKならリターンキーを押してください。 検索、置換が始まります。 検索の最中は、リターンキーで次の候補を探しにいきます。 置換ではリターンキーは「置換してもいい」という指示を兼ねます。 置換したくない場合はリターンキー、ブレイクキー以外のキーを 押してください。 置換せずに次の候補を探します。 どちらのコマンドもブレイクキーで終了します。 置換語、検索語は半角20文字以内で、 コントロールコードを合めて検索できます。 たとえば「LD《タブ》」を探すなら、  [L][D][^][I] と入力してください (コントロールコードの表記法はアセンブラの解説を参照)。 ・―               ―・ |    エディット モード    | ・―               ―・ コマンドモードの“E”コマンドで入ります。 エディットモードに入るとカーソルは画面の最上段の行に移動し、 行番号の直後にある空白のところで点滅を始めます。 ここはコントロールカラムです。 コントロールカラムに表2の文字を書き込むことで、 削除や挿入などの編集作業を行います。 特に画面スクロール関係は充実していますので、 慣れればエディットモードから抜けることなく 編集作業のすべてを行うことができるようになるでしょう。 それぞれのコマンドを説明します。 表2 エディットモード ・――――――――――――――――――――――・ | +:現在行の後ろに空白行を10行挿入    | | −:現在行を削除             | | /:現在行と,続く改行だけの行を削除   | | .:現在行をマーク            | | ,:現在行とマーク行を交換        | | [:現在行から表示する          | | =:現在行を画面の中心に表示       | | ]:現在行の前の行を最下行に       | | (:前の画面を表示            | | ):次の両面を表示            | | <:マーク行から現在行までを削除     | | >:削除した行を現在行の前に挿入     | ・――――――――――――――――――――――・ ●行の挿入と削除 最初にテキストを書き込むときは、 コントロールカラムに“+”を書いてから書き始めます。 リターンキーを押すと、 入力した行の「下に」10行新しい行ができます。 このエディタでは行番号のないところに テキストを書くことはできませんので、 “+”コマンドを使って新しい行を作成してから、 テキストを書き込むというのが基本作業になります。 不必要な行はコントロールカラムに“−”を書いて リターンキーを押すと削除されます。 “/”コマンドは、 なにも書いてない複数の行を削除するのに使用します。 これは主に、“+”コマンドであけすぎた行を削除するのに使います。 とりあえず何行か“+”コマンドであけておいて、 テキストを作った結果、不要な行ができたら “/”で削る、といういい加減なプログラミングが可能なのです。 ●行のマークとマークヘのジャンプ プログラムを作っている最中に、 呼び出そうとしているサブルーチンには どのレジスタで値を渡すのだったかを調べたいなど、 ちょっと現在いる行を離れたくなることがよくあります。 エディタは行番号のマークという手段でこれをサポートしました。 コントロールカラムに“.”をつけてリターンキーを押すと、 その行番号をエディタは記憶します。 そして任意の行のコントロールカラムで“,”コマンドを使用すると、 マークした行へ帰ってきます。 このときエディタは“,”コマンドが 実行された行を新しいマーク行として記憶します。 ですからここでもう一度“,”コマンドを使用すると、 さっきまでながめていた行に飛んでいくことができます。 つまり、テキストの2つの場所をいったりきたりできるわけです。 ●画面スクロールの制御 プログラムを自由にながめるため、 スクロール系のコマンドが充実しています。 コントロールカラムに“[”コマンドを書くと、 その行から再表示されます。 サブルーチンの最初が画面の下部に表示され、 全体を見ることができないときに便利でしょう。 逆に“]”コマンドは、 その行の直前の行を画面最下行として表示し直します。 サブルーチンの終わりが画面の上部に表示されたときに便利です。 “=”コマンドは、その行が画面中央になるように再表示します。 “(”コマンドと“)”コマンドは、 エディットモードを抜けなくても ページスクロールできるようにしたものです。 複数行のスクロールには向きませんが、 1、2ページなら楽に使えるでしょう。 残った“<”と“>”の2つのコマンドは、 次節で説明しましょう。 エディットモードを終了するには、 ブレイクキーまたはシフトブレイクを押します。 ●テキストのカットとコピー エディタで任意の複数行を削除する方法はちょっと変わっています。 削除を行う“<”は、 「マーク行から“<”が入力された直前の行までをを削除する」 というコマンドです。 削除するには、まず削除を始めたい行をマークします。 そして削除最終行の次の行で“<”コマンドを使用するわけです。 〜行から〜行までを削除するという方法では、 削除開始行、あるいは削除終了行を覚えておかなければなりません。 ここではこの非人間的な方法を排除しました。 削除した行はバッファに保存してあり、 次に削除が行われるまで内容が保存されています (もちろん電源を落としたらパー)。 削除した行をバッファから取り出すのが“>”コマンドです。 エディタには削除のみでコピーが用意されていませんが、 コピーはこのカットアンドペーストで対応します。 ●テクニカルサポート コマンドモードとエディットモードは それぞれが終了されるまでループを続けます。 エディタではループを構成するのに ちょっと変わった方法を使用しています。 それぞれのループの最初で ループの先頭アドレスをPUSHしておき、 サブルーチンにはJPで飛んでいくのです。 これは決してほめられた プログラミングテクニックではありませんが、 プログラムが短くなるという唯一のメリットを持っています。   LP0: CP 'Z'    JR NZ,LP1    CALL SCRLDWN    JR LPEND   LP1: CP 'V'    JR NZ,〜    CALL SCRLUP    JR LPEND       :       :   LPEND: などという面倒なプログラムが、   LOOP:LD HL,LOOP    PUSH HL    CP 'Z'    JP Z,SCRLDWN    CP 'V'    JP Z,SCRLUP       :       : とあっさり片づきます。 MC 68000のように 馬鹿デカイメモリを持っているならいいのですが、 Z80には64Kバイトしかありません。 ループを実現するこの手法は“必要悪”といえると思います。 実際のプログラムは「CP〜」「JP Z,〜 」を テーブル参照を使ってさらに短くしています。 なお、エディタ部はアセンブルし直せば アセンブラと独立して動作可能です。 ソースプログラムでは、 「#TXTST」というラベルが定義してあり、 プログラム先頭のジャンプ命令の次から始まる 内部ワークエリアの「#TXTST」はコメントとして殺してあります。 ラベル定義を削除し、 ワークエリアの「#TXTST」を復活させ、 好きなアドレスでアセンブルしてください。 3000Hにアセンブルすれば、分離したアセンブラとの併用で、 これまでにない大きなプログラムを作成できるようになります。 ===================      アセンブラ部       〈REDAの文法〉 ――――――――――――――――――― 起動時および、エディタからQコマンドで抜けると アセンブラモードに入ります。 アセンブラモードでは表3のコマンドが使えます。 表3 アセンブラコマンド ・――――――――――――――――――――――――――――――――・ |A[/]                            | | メモリ上にあるソーステキストをアセンブルする。        | | 『/』が指定された場合は                   | | 2パス目でアセンブルリストを                 | | 画面・プリンタに出力する。                  | |                                | |A[/]ファイル名[:ファイル名[…]]            | | デバイスからソーステキストをロードし、            | | アセンブルする。                       | | 複数のファイルが指定されたときは、              | | それらを順にアセンブルする。                 | | SスイッチがON、FスイッチがOFFになっている場合は、   | | 1ファイルアセンブルするごとに                | | オブジェクトをセーブするかどうかを              | | 確認するメッセージが表示され、                | | ここでYキーまたはリターンキーを押せば、           | | オブジェクトがセーブされる。                 | | S、FスイッチがともにONのときは、             | | すべてのファイルのアセンブルが終了した時点で、        | | セーブするかどうかの確認メッセージが表示される。       | |                                | |S ssss eeee xxxx[oooo]:ファイル名            | | ssssHからeeeeHまでを 実行アドレスxxxxHで         | | セーブする。                         | | ooooが指定されたときは、                   | | ooooH以降のメモリをssssHに                 | | ロードされるような形式でセーブする              | | (ooooはOFFSETをつけたときに使用する)         | |                                | |O                               | | アセンブル後、定義されたラベルの一覧を            | | 画面・プリンタに出力する。                  | |                                | |?式                              | | 式の値を計算し、表示する。                  | |                                | |#                               | | 一度実行するごとに、アセンブルリストおよび          | | ラベルの一覧を画面のみに表示するか、             | | 両面とプリンタに同時に出力するかどうかが切り換わる。     | | デフォルトはOFF。                     | |                                | |/[スイッチ[+|−][…]]                 | | アセンブルオプションスイッチのON/OFFを切り換え、    | | 状況を報告する。                       | | スイッチには本文で述べた7種類があり、            | | ONにするときは直後に「+」を、               | | OFFにするときは直後に「−」を置いて指定する。       | | 「+」は省略可能。                      | | 複数の指定を羅列することができ、               | | また、指定したスイッチは再び切り換え直すまで有効。      | | デフォルトは全スイッチOFF。                | |                                | |X[テキスト先頭アドレス]                   | | ソーステキスト格納先頭アドレスを指定する。          | | デフォルトは5000H番地。                   | |                                | |P[オブジェクト領域先頭アドレス[終了アドレス]]       | | アセンブル時、オブジェクトを生成してもかまわない       | | メモリ領域の範囲を指定する。                 | | MスイッチがONの状態でアセンブル中に、           | | このコマンドで指定した以外のメモリ領域に           | | オブジェクトを生成しようとするとエラーが発生する。      | | デフォルトは5000H〜#MEMAX。                 | |                                | |D[デバイス名:]                       | | デバイスのディレクトリをとる。                | |                                | |V[デバイス名:]                       | | セミオートアセンブル時にオブジェクトを            | | セーブするデバイスの切り換え、および表示を行う。       | | デフォルトはA:。                      | |                                | |E                               | | エディタが組み込まれていれば、エディットモードに入る。    | |                                | |Q                               | | アセンブラを抜け、呼び出したシステムに復帰する。       | |                                | ・――――――――――――――――――――――――――――――――・ すでにメモリ上にアセンブリソースが存在するなら、   :A でアセンブルが行われ、マシン語プログラムが生成されます。 REDAは2パス構成のアセンブラであり、 ソースリストを2度続けて解析します。 1パス目はラベルの値を決めるためのもので、 2パス目で実際にオブジェクトを生成します。 アセンブル終了後、定義されたラベルの総数と、 オブジェクトの開始アドレス・終了アドレス・実行アドレス・ 生成された先頭アドレスが表示されます。 REDAでのアセンブリソースは、次のような規則に従います。 1)各行はラベル定義部、命令文、注釈のフィールドから成ります。   必要がなければ、このうちのひとつもしくはすべてを   省略してもかまいません。 2)ラベルは行頭に置くことで定義されます。   このときラベルであることを明示するために、   直後に「:」をつけることが推奨されています。 3)命令文はZ80のザイログニーモニックか、   このアセンブラの疑似命令(表4)です。 4)命令文は必ず行頭から1文字以上空けて書き始めなければなりません。   が、特に「.LIST」と「.NLIST」の2つの疑似命令は   行頭に置くことが許されています。 5)「;」以降は注釈です。   また、のちほど述べますアセンブルスイッチにより   構文チェックを厳しくしない限り、   命令文の直後から行の終わりまでも注釈とみなされ、   アセンブラはこれを無視します。   そのほか、細かな点は表5にまとめておきます。 表4 擬似命令 ・―――――――――――――――――――――――――――――――――――――・ |ORGnn                                | | アセンブルするマシン語プログラムの先頭アドレスを指定する。       | | 基本的に各ソーステキストの先頭で必ず宣言する必要があり、        | | 指定がないときは0000Hからオブジェクトを生成する。           | |  例) ORG 8000H                         | | なお、ORGはひとつのファイル中に複数置くことができるが、       | | アドレスをさかのぼる宣言は認められていない。              | |  例) ORG 8000H                         | |          :                          | |     ORG 7000H                         | |            はエラー                     | |                                     | |OFFSET nn                            | | アセンブルしたオブジェクトをORGで指定したアドレスとは        | | 別の領域に生成するときに使用し、                    | | nnで生成アドレスと先頭アドレスとの差を指定する。           | | 次の例では「3000H番地にロードされたとき動作するプログラム」を     | | 8000H番地以降に生成する。                       | |  例) OFFSET 8000H-3000H                      | |     ORG 3000H                         | | なお、OFFSETは各ソースにただひとつのみ存在し、          | | すべてのORGに先立って宣言されなければならない。           | |                                     | |EQU nn                               | | ラベルに値を定義する。                         | | nnにラベルを使う場合は、                       | | そのラベルの値がすでに確定していなければならない            | | (ただし、2パス構成のアセンブラであるため、              | |  ラベルの前方参照は1段階に限り許される)。              | |  例)  #PRINT EQU 1FF4H                     | |                                     | |DEFB n または DB n                      | | 1バイト単位の定数をそのままオブジェクトとして生成する。        | | 「,」または「:」で区切って複数並べることができる。          | |  例)  DEFB 0,34H,'A':"B"                     | |                                     | |DEFB‘文字列’または DB‘文字列’                 | | 「’」または「”」で囲まれた文字列を、                 | | 先頭から順に1バイトずつオブジェクトとして生成する。          | | 文字列の中では表6のエスケープシーケンスが使用できる。         | | 「,」または「:」で区切って複数並べることができ、           | | また、DEFB n の形式との混在も可能。               | |  例) DEFB 'TEST'                         | |     DEFB '^'TEST^'^M^@'                     | |     DEFB 27H,'TEST',27H,13H,00H                 | |                                     | |DEFW nn または DW nn                    | | 2バイトの定数を下位バイト、上位バイトの順に、             | | そのままオブジェクトとして生成する。                  | | 「,」または「:」で区切って複数並べることができる。          | |  例) DEFW 1234H,5678H                       | |                                     | |DEFS nn または DSnn                     | | nnバイトのメモリ領域を確保する。                   | | nnは未定義のラベルであってはならない。                | | 標準の状態では確保したメモリの値は不定だが、              | | アセンブルオプションスイッチCをONにすることで、           | | 0で埋めるように強制することができる。                 | |  例) WORK: DEFS 2                       | |                                     | |DEFM‘文字列’ または DM‘文字列’                | | 「’」または「”」で囲まれた文字列を、                 | | 先頭から順に1バイトずつオブジェクトとして生成する。          | | 文字列の中では表6のエスケープシーケンスが使用可能。          | |  例) DEFM 'TEST'                         | |                                     | |.NLIST                               | | A/でアセンブル中のみ有効。                      | | アセンブルリスト出力をOFFにする。                  | | この命令の置かれた行から                        | | 次に「.LIST」に出合うまでの範囲は                 | | アセンブルリストが出力されない。                    | | なお、この命令と、次項の「.LIST」は、               | | 特に先行するスペースなしに、行頭から記述することが許される。      | | 例) .NLIST                             | |   .NLIST                               | |                                     | |.LIST                                | | .NLISTで禁止したアセンブルリスト出力を再開する。         | | 例)  .LIST                              | |   .LIST                                | |                                     | |.LIST nn                             | | アセンブルリスト出力を再開すると同時に、                | | 出力する行番号をnnにつけ換える。                   | | この命令の次の行の行番号がnnとなる。                 | | 例)  .LIST 100                          | |   .LIST 100                            | ・―――――――――――――――――――――――――――――――――――――・ 表5 REDAの文法 ・―――――――――――――――――――――――――――――――――――――・ |◎数値                                  | | 定数またはラベルに定義された値、およびそれらからなる式。        | |                                     | |◎ラベル                                 | | 先頭が数字、「$」、「。」ではなく、                  | | スペース、タブ、「:」、「、」、「+」、「−」、            | | 「*」、「/」、「%」、「’」;「”」を含まない            | | 任意の半角文字からなる 255文字までの文字列を              | | ラベルとして認め、全文字識別する。                   | |                                     | |◎定数                                  | | 10進定数、16進定数、2進定数、文字定数、                | | および、特殊な定数としてS(その時点のロケーションカウンタ)。     | |                                     | |◎10進定数                                | | 0〜9の数字。                             | |                                     | |◎16進定数                                | | 「$」から始まる16進数、または、                    | | 0〜9で始まり「H」で終わる16進数。                  | | 例) $ABCD                               | |    0ABCDH                              | |                                     | |◎2進定数                                | | 「%」から始まる2進数、                        | | または、「B」で終わる2進数。                     | | 例) %01011001                             | |    01011001B                             | |                                     | |◎文字定数                                | | 「’」または「”」で囲まれた1文字のASCIIコード。         | | 表6のエスケープシーケンスが使用可能。                 | |                                     | |◎そのほかの定数                             | | 単独の「$」はそれが置かれた行のアドレスを表す定数として        | | 用いることができる。                          | | 例)     DJNZ $                          | |         ||                           | |    LABE:  DJNZ LABEL                        | |                                     | |◎式                                   | | 加減乗除、および剰余(%)が使用できる。                | |  (小)+、− < *、/、%(大)                  | | の優先順位に従って計算される。                     | | カッコは使用できない。                         | | また、オーバーフローは無視される。                   | ・―――――――――――――――――――――――――――――――――――――・ 表6 エスケープシーケンス ・――――――――――――――――――――――・ |    ^@ = 00H           | |    ^A = 01H           | |    ^B = 02H           | |       :              | |    ^Z = 1AH           | |    ^[ = 1BH           | |    ^” = 22H           | |    ^’ = 27H           | |    ^^ = 5EH           | |注)^Aは[^][A]のように2文字で表記する | ・――――――――――――――――――――――・ 表7 アセンブルエラー ・―――――――――――――――――――――――――――――――――――――・ |◎Illegal opecode Error               | | オペコードが正しくない                         | | (ミスタイプか、さもなければ注釈の頭に「;」をつけ忘れたか)      | |                                     | |◎Illegal operand Error               | | オペランドが正しくない                         | | (ザイログニーモニックにはEX HL,DEはないし、          | |  SUB HL,BCもない)                      | |                                     | |◎Undefined Label Error               | | 未定義のラベルを使った                         | |                                     | |◎Redefinition Error                  | | ラベルの2重定義を行った                        | |                                     | |◎Illegal Label Error                 | | ラベルに使用できない文字を使った                    | | (特に「%」と「,」に注意)                      | |                                     | |◎Too Many Labels Error               | | ラベルテーブルもしくはハッシュテーブルがいっぱいになった        | |                                     | |◎Missing Label Error                 | | ラベルが置かれるべき位置にラベルがない                 | | (行頭にいきなりコロンがあるとか)                   | |                                     | |◎Too Far Error                       | | 相対分岐可能な範囲外に分岐しようとした                 | |                                     | |◎Illegal Expression Error            | | 式が正しくない                             | | (数値としては使えない文字が含まれている可能性が高い。         | |  また、除算時の分母が0または                     | |  未定義のラベルの場合にも発生する)                  | |                                     | |◎Missing [)]Error                    | | カッコが閉じていない                          | |                                     | |◎Missing[,]Error                     | | あるべきはずのカンマがない                       | |                                     | |◎Missing Quote Error                 | | 文字列が閉じていない                          | | (クォーテーションマークのつけ忘れか、                 | |  そうでなければエスケープシーケンスに誤りがあるかもしれない)     | |                                     | |◎Illegal ORG Error                   | | 不正なORGがある                           | | (アドレスをさかのぼるORG宣言は認められていない)          | |                                     | |◎Illegal OFFSET Error                | | 不正なOFFSETがある                        | | (OFFSETはソース中でただひとつ、                 | |  すべてのORGに先立って宣言されなければならない。          | |  ただし、分割アセンブル時にはひとつのファイルで            | |  それぞれのOFFSETが指定可)                   | |                                     | |◎Memory Error                        | | 決められた範囲外のメモリにオブジェクトを生成しようとした        | | (MスイッチがONのときのみ発生。                   | |  ORGやOFFSETのつけ忘れが考えられる)             | |                                     | |◎Syntax Error                        | | そのほかの文法上エラー                         | ・―――――――――――――――――――――――――――――――――――――・ ・―               ―・ | アセンブルオプションスイッチ  | ・―               ―・ REDAにはエラーチェックをより厳しくするものと、 モードを切り換えるものとの 計7つのアセンブルオプションスイッチがあります。 スイッチのON/OFF切り換え、および状態の報告は 「/」コマンドで行います。 試しに、   :/ と入力しますと、使用可能なスイッチの一覧と その状態(デフォルトではすべてOFF)が表示されます。 スイッチはここで表示された頭文字によって区別します。 スイッチをONにするには頭文字に続け、「+」を入力します。 OFFにするときは「−」です。 例を挙げますと、KスイッチをONにしたければ。   :/K+ OFFにしたければ。   :/K- となります。 ●Mスイッチ オブジェクトの生成先がPコマンドで指定された範囲に収まるかどうか チェックするようになります。 誰にでもORGをつけ忘れて オブジェクトが0000H番地から生成されてしまい、 システムを破壊して暴走したという経験があるでしょう。 このスイッチをONにしておけば、 変なアドレスにオブジェクトを生成しようとした時点で エラーが出て止まりますから、安全に作業することができます。 ●Lスイッチ ラベルテーブルがオーバーフローしたかどうか チェックするようになります。 REDAは特殊ワークをラベルテーブルに使っていますから、 定義できるラベルの最大数はその大きさに依存します。 標準の状態ではラベルテーブルのあぶれをチェックしていませんが、 Lスイッチは、そのチェックを行うようにするものです。 なお、REDAではラベル検索を高速化するために ハッシュテーブルを導入しており定義できるラベルの最大数は このハッシュテーブルの大きさにも制限されます (起動時に表示される値がそうです)。 Lスイッチの状態にかかわらず、 ハッシュテーブルのあふれは常にチェックされています。 ●Eスイッチ テキスト行末にコメント以外の文字列があるかどうか チェックするようにします。 REDAではマルチステートメントが許されていませんので、 ZEDAのテキストをそのまま使うときは、 このスイッチをONにして、 マルチステートメントがないことを確認するのがよいでしょう。 ●Cスイッチ DEFSで確保した領域を0で埋めるようになります。 DEFSで確保した領域は プログラムで初期化するのが自然だと考え、 REDAでは0でクリアしないようにしてあります。 もし、領域が0でクリアされているのを 前提で作られたプログラムがありましたら、 CスイッチをONにしてアセンブルしてください。 ●Kスイッチ 文字列中に全角文字を使用するとき指定します。 エスケープ文字として「^」を採用した結果、 シフトJISコードの2バイト目と 「^」を混同する可能性が出てきてしまいました。 S−OSでは漢字はオプション扱いではありますが、 REDAはなにもS−OS用のプログラムを 作るためのみにあるわけではありませんから、 漢字が使えないというのも困ります。 というわけで、このKスイッチが追加されました。 メッセージに全角文字を使う場合には、 忘れずにこのスイッチをONにしてください。 ●Sスイッチ アセンブル後、生成されたオブジェクトをセーブするかどうか 聞いてくるようになります。 ただし、メモリ上のテキストをアセンブルした場合は無効です。 ●Fスイッチ 断片アセンブルモードにします。 これについては次項以降で説明します。 ・―               ―・ |     分割アセンブル     | ・―               ―・ REDAはZEDA−3に見られたようなかたちの分割アセンブル、 つまり複数ファイルの連続アセンブルをサポートします。 これにより、メモリ量の制約なしに、 大きなプログラムを作成することができます。 ZEDA−3では手作業で ファイルのロード/アセンブルを実行していましたが、 REDAではそのあたりのことは プログラム側で処理しています。 半面、ファイルの分割は コマンドラインの1行で指定できる数までに制限されています。 分割アセンブルは次のような手順で行います。  1)ソースリストを適当な大きさに分割し、    セーブしておきます。    ここではAAA、BBBの2つのファイルに分割したとします。    OFFSETを指定し、    ソースを破壊しつつアセンブルすることを前提にすれば、    それぞれのファイルはメモリ量ギリギリの大きさにとることができます。  2)分割した1番目のリストの最後に適当なラベルをつけます。    ここでは仮にAENDとします。  3)2番目のリストの先頭にORGと必要であれば    OFFSETをつけ足します。    このときORGアドレスとして、    1番目のリストの最後につけたラベルを使用します。    例の場合ですと     ORG AEND    となります。  4)同様の作業をすべてのリストに対して行い、    セーブし直します。    なお、テープにセーブする場合は、    すべてのソースは1本のテープに    「アセンブルする順番」にセーブしておく必要があります。  5)ここで     :/F-    によって、アセンブルスイッチFをOFFにしておきます。    また、ソースを破壊しつつアセンブルする場合には、    ここでアセンブルオプションスイッチSをONにし、    ファイルひとつごとにオブジェクトをセーブするモードに    しておく必要があります。    つまり、連続してロードされるソースファイルによって、    生成されたオブジェクトが上書きされてしまう前に    セーブできるようにするのです。    指定の方法は、     :/S+    です。  6)REDAのアセンブルモードで、     :A    に続けてファイル名を1番目から順にコロンで区切って並べます。    いまの場合ですと     :A AAA:BBB    となります。  7)次々にファイルが読み込まれ、アセンブル(1パス目)されます。    ソースファイルを2度読みする必要上、    テープ使用時にはパス1が終了した時点でメッセージが出ますので、    テープを巻き戻し、なにかキーを押してください。  8)再び、ファイルが順次読み込まれ、アセンブル(2パス目)されます。    SスイッチがONのときは、    ファイルひとつのアセンブルがすむごとに    セーブするかどうかの確認メッセージが出ますので、    セーブしたければ“Y”を入力してください。    すると、Vコマンドで指定されたデバイスに、    ソースファイル名の拡張子を「.OBJ」にした名前で    オブジェクトがセーブされます。    なお、セーブするデバイスがテープ・QDの場合は、    メッセージに従って(必要であれば)    テープ・QDの交換を行ってください。 ・―               ―・ |     断片アセンブル     | ・―               ―・ また、REDAでは以上のZEDA−3方式に加え、 断片アセンブルなるモードをサポートします。 感じとしては、このモードのほうが 「分割」アセンブルという言葉のイメージに近いのですが、 すでにある用語と混乱しても困りますので、 断片アセンブルという言葉をでっちあげました。 これは次の手順で行います。 1)ソースリストを適当な大きさに分割し、セーブしておきます。   このとき、ひとつのファイルの大きさは   「メモリの空き領域―生成されるオブジェクトの大きさ」までに   制限されます。   つまり、最終的に生成されるマシン語プログラムを   格納しておけるだけのメモリを確保しておかなければなりません。   また、ソースを破壊しながらのアセンブルは行えません。 2)アセンブルオプションスイッチFをONにします。   具体的には。    :/F+   とします。 3):Aに続けてファイル名を1番目から順にコロンで区切って並べます。 4)次々にファイルが読み込まれ、アセンブルされます。 5)SスイッチがONのときは、全ソースのアセンブルが終了した吽点で、   オブジェクトをセーブするかどうか確認してきますので、   セーブするのであればYまたはリターンキーを、   しないのであればNキーを押してください。   セーブする場合のファイル名は   最初のソースのファイル名の拡張子を「.OBJ」にしたものになります。 ・―               ―・ |   REDAのカスタマイズ   | ・―               ―・ REDAは起動時にアセンブルオプションスイッチなどの初期化を行いません。 これを利用して、一度REDAを立ち上げ、 スイッチの設定を行ってからセーブし直すことで、 容易にデフォルトの環境を変更することができます。 設定可能なのは次の5項目です。  1)アセンブルオプションスイッチ(/コマンド)  2)テキスト格納アドレス(Xコマンド)  3)オブジェクト生成可能アドレスの下限値(Pコマンド)  4)オブジェクトをセーブするデバイス名(Vコマンド)  5)プリンタのON/OFF(#コマンド) また、メモリ番地を直接書き換えることで、以下の設定も可能です。 1)エディタを組み込むかどうか  (3005H番地:00Hなら非組み込み、FFHなら組み込み)。 2)オブジェクトセーブ時の拡張子  (3023H番地からの3バイト:拡張子をASCII コードで並べる。   3バイトに満たないときは残りをスペースで埋める)。 ・―               ―・ |     開発を終えて      | ・―               ―・ REDAは純粋に道具として使う目的で作成されました。 それと同時に、マシン語入門者にとっても扱いやすいよう配慮したつもりです。 ZEDAのような疑似マクロがあったほうが 入門者にとってはありがたかったのではないかという意見もあるでしょうが、 私はそれに関しては逆の意見です。 入門者こそ、生のニーモニックで 細部でのレジスタの値やフラグの変化を感じ取りながら プログラムを作っていくべきだと考えます。 それはともかく、最近は手に入れることもできず、 高速化だのなんのといいながらパッチ当てだらけにされてしまった (みんな私が悪いんです) ZEDAに代わって、新しいアセンブラをいちから制作し、 発表することができたのは嬉しいかぎりです。 アセンブラはツールでしかありません。 あとは読者の皆さんの力で使いこなしてやってください。 付録ZEDAとの互換性 ・――――――――――――――――――――――――――――――――・ | ZEDAのテキストを利用するときは以下の点に注意してください。| |                                | |1)疑似マクロ                         | | ZEDAでは使えたIFやそのほかの疑似マクロを        | | REDAはサポートしていません。               | | 正しいザイログニーモニックに展開してください。        | |  例) IF A=0 JR TEST                    | |        ↓                       | |     OR A                        | |     JR Z,TEST                      | |                                | |                                | |     SUB HL,DE                      | |        ↓                       | |     OR A                        | |     SBC HL,DE                      | |                                | |2)マルチステートメント                    | |  REDAではマルチステートメントを認めていません。     | |  マルチステートメントはすべて展開してください。       | |  なお、アセンブルオプションスイッチEをONにすることで、  | |  マルチステートメントが行われているかどうかを        | |  チェックすることができます。                | |                                | |3)ラベルに使える文字                     | |  「%」が使用できなくなりました。              | |  また、ラベルの先頭に「.」は使えません。          | |                                | |4)エスケープシーケンス                    | |  文字列中の「^」はエスケープ文字として機能します。     | |  文字列のなかで「^」を使っている場合は、          | |  それを「^^」に変更してください。             | |   例) DEFM '^V^'                     | |        ↓                       | |      DEFM '^^V^^'                    | |                                | |5)演算子の優先順位                      | |  ZEDAでは演算子に優先順位がありませんでしたが、     | |  REDAは一般的な演算子の優先順位に従って         | |  式の評価を行います。                    | |  そのため,場合によっては式を変形しないと          | |  ZEDAと同じ値が得られないことがあります。        | |   例) 1+2*3は                    | |      ZEDAでは(1+2)*3=9           | |      REDAでは1+(2*3)=7           | |      となります。                    | |                                | ・――――――――――――――――――――――――――――――――・